package panda.record;

import static java.sql.Types.FLOAT;
import static java.sql.Types.INTEGER;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import panda.file.Page;

/**
 * The token of a table, containing complete information about the table
 * 
 * @author Tian Yuan
 */
public class TableToken {
	private String name;

	private Schema schema;

	private Map<String, Integer> offsets;

	private int recLen;

	public TableToken(String tableName, Schema schema) {
		this.name = tableName;
		this.schema = schema;
		offsets = new HashMap<String, Integer>();
		int pos = 0;
		Collection<String> attrs = schema.getAllAttributeNames();
		for (String i : attrs) {
			offsets.put(i, pos);
			pos += attributeLength(schema, i);
		}
		recLen = pos;
	}

	public TableToken(String tableName, Schema schema,
			Map<String, Integer> offsets, int recLen) {
		this.name = tableName;
		this.schema = schema;
		this.offsets = offsets;
		this.recLen = recLen;
	}

	/**
	 * Return the schema of the table
	 * 
	 * @return
	 */
	public Schema getSchema() {
		return schema;
	}

	/**
	 * Get the length of the this tuple in repository
	 * 
	 * @return length in BYTE
	 */
	public int getTupleLength() {
		return recLen;
	}

	/**
	 * Get the name of the file containing this table
	 * 
	 * @return the filename
	 */
	public String getFilename() {
		return name;
	}

	/**
	 * Calculate the length of the specific attribute
	 * 
	 * @param name
	 *            the name of the attribute
	 * @return the length in BYTE
	 */
	private static int attributeLength(Schema schema, String fieldName) {
		int type = schema.getType(fieldName);
		if (type == INTEGER)
			return Page.INT_SIZE;
		if (type == FLOAT)
			return Page.FLOAT_SIZE;
		if (type == java.sql.Types.CHAR)
			return Page.STR_SIZE(schema.getLength(fieldName));
		if (type == java.sql.Types.VARCHAR)
			return Page.STR_SIZE(schema.getLength(fieldName));
		if (type == java.sql.Types.DATE)
			return Page.STR_SIZE(20);
		if (type == java.sql.Types.TIMESTAMP)
			return Page.STR_SIZE(20);
		// TODO add other types here
		return 0;
	}

	/**
	 * Get the length of a tuple under the specific schema
	 * 
	 * @param sch
	 *            the given schema
	 * @return the length of a tuple
	 */
	public static int getTupleLength(Schema sch) {
		Collection<String> attrs = sch.getAllAttributeNames();
		int pos = 0;

		for (String i : attrs)
			pos += attributeLength(sch, i);

		return pos;
	}

	public int offsetOf(String attribute) {
		return offsets.get(attribute);
	}

	/**
	 * Get the name of the specified table
	 * 
	 * @return the table name
	 */
	public String getTableName() {
		return name;
	}
}
